"""
IoT统一控制器
IoT Unified Controller

整合所有IoT设备的统一API接口，替代原有的设备特定控制器
Unified API interface for all IoT devices, replacing the original device-specific controllers
"""

import logging
from typing import Dict, Any, List, Optional
from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel

# 导入IoT模块 / Import IoT modules
from iot.services.device_manager import device_manager
from iot.services.data_processor import data_processor
from iot.services.command_handler import command_handler, CommandType

# 导入原有的数据模型以保持兼容性 / Import original data models for compatibility
from model.wristband_models import LocationData, HealthData, BatteryData, WarningData, AudioData

# 导入重构后的处理服务 / Import refactored processing services
from iot.services.handler_manager import (
    location_handle_new, handle_health, handle_step, 
    handle_warning, handle_audio
)

# 导入工具函数 / Import utility functions
from utils.logger_util import logger, save_data_log_mongo
from dao.es_dao.card_dao import find_imei

logger = logging.getLogger(__name__)

# 创建统一路由器 / Create unified router
iot_router = APIRouter(prefix="/iot", tags=['IoT统一接口 / IoT Unified Interface'])

# 模型路由映射表 / Model routing mapper
MODEL_ROUTER = {
    "location": LocationData,
    "health": HealthData,
    "battery": BatteryData,
    "warning": WarningData,
    "audio": AudioData
}

# 核心处理器映射表 / Core handler mapper
HANDLER_MAPPER = {
    "location": location_handle_new,
    "health": handle_health,
    "battery": handle_step,
    "warning": handle_warning,
    "audio": handle_audio
}


class DeviceDataRequest(BaseModel):
    """
    设备数据请求模型
    Device data request model
    """
    device_id: str
    device_type: Optional[str] = None
    data: Dict[str, Any]


class BatchDataRequest(BaseModel):
    """
    批量数据请求模型
    Batch data request model
    """
    items: List[Dict[str, Any]]


class CommandRequest(BaseModel):
    """
    命令请求模型
    Command request model
    """
    device_id: str
    command_type: str
    command_data: Dict[str, Any]
    timeout: Optional[int] = None


class BatchCommandRequest(BaseModel):
    """
    批量命令请求模型
    Batch command request model
    """
    device_ids: List[str]
    command_type: str
    command_data: Dict[str, Any]
    timeout: Optional[int] = None


async def dynamic_model_router(action: str, raw_data: Dict[str, Any]) -> BaseModel:
    """动态选择并验证数据模型 / Dynamic model selection and validation"""
    model_class = MODEL_ROUTER.get(action)
    if not model_class:
        raise ValueError(f"未知的 action 类型 / Unknown action type: {action}")

    try:
        # Pydantic 自动验证并转换数据类型 / Pydantic automatic validation and type conversion
        return model_class(**raw_data)
    except Exception as e:
        logger.error(f"数据验证失败 / Data validation failed: {str(e)}")
        raise HTTPException(status_code=422, detail=str(e))


@iot_router.post("/data/process")
async def process_device_data(raw_data: Dict[str, Any]) -> Dict[str, Any]:
    """
    处理单个设备数据 - 基于action的路由处理
    Process single device data - Action-based routing processing
    
    统一的设备数据处理入口，支持所有设备类型
    Unified device data processing entry point, supports all device types
    """
    try:
        # 关键参数检查 / Key parameter validation
        if "action" not in raw_data:
            raise HTTPException(400, "缺少 action 参数 / Missing action parameter")

        action = raw_data["action"]
        device_id = raw_data.get("device_id") or raw_data.get("imei")
        if not device_id:
            raise HTTPException(400, "缺少设备ID / Missing device ID")
            
        logger.info(f"收到 {action} 类型请求，设备ID: {device_id} / Received {action} type request, device ID: {device_id}")
        
        # 保存原始日志（兼容性）/ Save original log (compatibility)
        await save_data_log_mongo(raw_data)
        
        # 动态路由和模型验证 / Dynamic routing and model validation
        validated_data: BaseModel = await dynamic_model_router(action, raw_data)
        
        # 执行对应处理器 / Execute corresponding handler
        handler = HANDLER_MAPPER.get(action)
        if not handler:
            raise ValueError(f"未注册的 action 处理器 / Unregistered action handler: {action}")

        await handler(validated_data)
        
        return {"status": 1, "message": "处理成功 / Processing successful"}
        
    except HTTPException:
        raise
    except Exception as e:
        logger.exception(f"处理设备数据时发生异常 / Exception occurred while processing device data")
        raise HTTPException(status_code=500, detail=f"数据处理失败 / Data processing failed: {str(e)}")


@iot_router.post("/data/batch")
async def process_batch_data(request: BatchDataRequest) -> Dict[str, Any]:
    """
    批量处理设备数据
    Batch process device data
    
    支持同时处理多个设备的数据
    Supports processing data from multiple devices simultaneously
    """
    try:
        logger.info(f"收到批量数据处理请求 / Received batch data processing request: {len(request.items)} items")
        
        # 使用IoT数据处理器批量处理数据 / Use IoT data processor for batch processing
        result = await data_processor.batch_process_data(request.items)
        
        return result
        
    except Exception as e:
        logger.exception("批量处理设备数据时发生异常 / Exception occurred during batch processing")
        raise HTTPException(status_code=500, detail=f"批量数据处理失败 / Batch data processing failed: {str(e)}")


@iot_router.post("/command/send")
async def send_device_command(request: CommandRequest) -> Dict[str, Any]:
    """
    向设备发送命令
    Send command to device
    
    统一的设备命令发送接口
    Unified device command sending interface
    """
    try:
        logger.info(f"收到设备命令发送请求 / Received device command sending request: {request.device_id}")
        
        # 转换命令类型 / Convert command type
        try:
            cmd_type = CommandType(request.command_type)
        except ValueError:
            cmd_type = CommandType.CUSTOM
        
        # 使用IoT命令处理器发送命令 / Use IoT command handler to send command
        result = await command_handler.send_command(
            request.device_id, 
            cmd_type, 
            request.command_data, 
            request.timeout
        )
        
        return result
        
    except Exception as e:
        logger.exception(f"发送设备命令时发生异常 / Exception occurred while sending device command: {request.device_id}")
        raise HTTPException(status_code=500, detail=f"命令发送失败 / Command sending failed: {str(e)}")


@iot_router.post("/command/batch")
async def send_batch_command(request: BatchCommandRequest) -> Dict[str, Any]:
    """
    批量发送命令
    Batch send command
    
    向多个设备批量发送相同命令
    Send same command to multiple devices in batch
    """
    try:
        logger.info(f"收到批量命令发送请求 / Received batch command sending request: {len(request.device_ids)} devices")
        
        # 转换命令类型 / Convert command type
        try:
            cmd_type = CommandType(request.command_type)
        except ValueError:
            cmd_type = CommandType.CUSTOM
        
        # 使用IoT命令处理器批量发送命令 / Use IoT command handler for batch command sending
        result = await command_handler.batch_send_command(
            request.device_ids,
            cmd_type,
            request.command_data,
            request.timeout
        )
        
        return result
        
    except Exception as e:
        logger.exception("批量发送命令时发生异常 / Exception occurred during batch command sending")
        raise HTTPException(status_code=500, detail=f"批量命令发送失败 / Batch command sending failed: {str(e)}")


@iot_router.get("/devices")
async def get_all_devices() -> Dict[str, Any]:
    """
    获取所有设备信息
    Get all devices information
    
    返回系统中所有已注册设备的详细信息
    Returns detailed information of all registered devices in the system
    """
    try:
        devices = device_manager.get_all_devices()
        device_list = []
        
        for device_id, device in devices.items():
            device_info = device.get_device_info()
            device_list.append(device_info)
        
        return {
            "total": len(device_list),
            "devices": device_list,
            "timestamp": data_processor.get_processing_statistics()["last_processed"]
        }
        
    except Exception as e:
        logger.exception("获取设备信息时发生异常 / Exception occurred while getting device information")
        raise HTTPException(status_code=500, detail=f"获取设备信息失败 / Failed to get device information: {str(e)}")


@iot_router.get("/devices/{device_id}")
async def get_device_info(device_id: str) -> Dict[str, Any]:
    """
    获取特定设备信息
    Get specific device information
    
    返回指定设备的详细信息和健康状态
    Returns detailed information and health status of the specified device
    """
    try:
        device = device_manager.get_device(device_id)
        if not device:
            raise HTTPException(status_code=404, detail=f"设备未找到 / Device not found: {device_id}")
        
        device_info = device.get_device_info()
        health_status = await device.health_check()
        
        return {
            "device_info": device_info,
            "health_status": health_status,
            "command_history": command_handler.get_device_command_history(device_id, 5)
        }
        
    except HTTPException:
        raise
    except Exception as e:
        logger.exception(f"获取设备信息时发生异常 / Exception occurred while getting device info: {device_id}")
        raise HTTPException(status_code=500, detail=f"获取设备信息失败 / Failed to get device info: {str(e)}")


@iot_router.get("/devices/type/{device_type}")
async def get_devices_by_type(device_type: str) -> Dict[str, Any]:
    """
    根据设备类型获取设备列表
    Get devices by type
    
    返回指定类型的所有设备
    Returns all devices of the specified type
    """
    try:
        devices = device_manager.get_devices_by_type(device_type.upper())
        device_list = []
        
        for device in devices:
            device_info = device.get_device_info()
            device_list.append(device_info)
        
        return {
            "device_type": device_type,
            "total": len(device_list),
            "devices": device_list
        }
        
    except Exception as e:
        logger.exception(f"根据类型获取设备时发生异常 / Exception occurred while getting devices by type: {device_type}")
        raise HTTPException(status_code=500, detail=f"获取设备列表失败 / Failed to get device list: {str(e)}")


@iot_router.get("/statistics")
async def get_system_statistics() -> Dict[str, Any]:
    """
    获取系统统计信息
    Get system statistics
    
    返回IoT系统的整体运行统计信息
    Returns overall operational statistics of the IoT system
    """
    try:
        device_stats = await device_manager.get_device_statistics()
        processing_stats = data_processor.get_processing_statistics()
        command_stats = command_handler.get_command_statistics()
        
        return {
            "device_statistics": device_stats,
            "processing_statistics": processing_stats,
            "command_statistics": command_stats,
            "system_status": "healthy" if device_stats.get("online_rate", 0) > 50 else "warning"
        }
        
    except Exception as e:
        logger.exception("获取系统统计信息时发生异常 / Exception occurred while getting system statistics")
        raise HTTPException(status_code=500, detail=f"获取统计信息失败 / Failed to get statistics: {str(e)}")


@iot_router.post("/health/batch")
async def batch_health_check(device_ids: Optional[List[str]] = None) -> Dict[str, Any]:
    """
    批量设备健康检查
    Batch device health check
    
    对指定设备进行健康状态检查
    Perform health status check on specified devices
    """
    try:
        health_results = await device_manager.batch_health_check(device_ids)
        
        return {
            "total_checked": len(health_results),
            "health_results": health_results,
            "timestamp": data_processor.get_processing_statistics()["last_processed"]
        }
        
    except Exception as e:
        logger.exception("批量健康检查时发生异常 / Exception occurred during batch health check")
        raise HTTPException(status_code=500, detail=f"健康检查失败 / Health check failed: {str(e)}")


# 兼容性API接口 / Compatibility API interfaces
# 保持与原有L16控制器的兼容性 / Maintain compatibility with original L16 controller

@iot_router.post("/l16/api")
async def l16_unified_api_entry(raw_data: Dict[str, Any]) -> Dict[str, Any]:
    """
    L16设备兼容性API入口
    L16 device compatibility API entry
    
    保持与原有L16接口的完全兼容性
    Maintains full compatibility with original L16 interface
    """
    try:
        # 提取设备ID / Extract device ID
        device_id = raw_data.get("device_id") or raw_data.get("imei")
        if not device_id:
            raise HTTPException(400, "缺少设备ID / Missing device ID")
        
        # 使用IoT数据处理器处理数据 / Use IoT data processor to process data
        result = await data_processor.process_device_data(device_id, raw_data)
        
        # 保持原有响应格式 / Maintain original response format
        if result.get("status") == "success":
            return {"status": 1, "message": "处理成功 / Processing successful"}
        else:
            return {"status": 0, "message": "处理失败 / Processing failed"}
        
    except Exception as e:
        logger.exception("L16兼容性API处理异常 / L16 compatibility API processing error")
        raise HTTPException(500, "服务器内部错误 / Internal server error")


@iot_router.post("/l16/command")
async def l16_command_compatibility(data: dict) -> dict:
    """
    L16命令兼容性接口
    L16 command compatibility interface
    
    保持与原有L16命令接口的兼容性
    Maintains compatibility with original L16 command interface
    """
    try:
        device_id = data.get("body", {}).get("imei")
        if not device_id:
            raise HTTPException(400, "缺少设备IMEI / Missing device IMEI")
        
        # 使用IoT命令处理器发送命令 / Use IoT command handler to send command
        result = await command_handler.send_command(
            device_id,
            CommandType.DEVICE_CONFIG,
            data
        )
        
        # 保持原有响应格式 / Maintain original response format
        return result.get("result", {"status": 1, "message": "命令发送成功 / Command sent successfully"})
        
    except Exception as e:
        logger.exception("L16命令兼容性接口处理异常 / L16 command compatibility interface processing error")
        raise HTTPException(500, "服务器内部错误 / Internal server error")


@iot_router.post("/l16/batch_command")
async def l16_batch_command_compatibility(data: dict) -> dict:
    """
    L16批量命令兼容性接口
    L16 batch command compatibility interface
    
    保持与原有L16批量命令接口的兼容性
    Maintains compatibility with original L16 batch command interface
    """
    try:
        imei_list = data.get('imei_list')
        if imei_list is None:
            if data.get('projectId') is not None:
                imei_list = await find_imei(data)
            else:
                return {"status": 0, "result": "设置失败 / Setup failed", "message": "缺少参数 / Missing parameters"}
        
        # 使用IoT命令处理器批量发送命令 / Use IoT command handler for batch command sending
        result = await command_handler.batch_send_command(
            imei_list,
            CommandType.DEVICE_CONFIG,
            data
        )
        
        # 保持原有响应格式 / Maintain original response format
        return {"status": 1, "result": result.get("results", [])}
        
    except Exception as e:
        logger.exception("L16批量命令兼容性接口处理异常 / L16 batch command compatibility interface processing error")
        return {"status": 0, "result": "批量命令失败 / Batch command failed", "message": str(e)}


# S8设备兼容性API / S8 device compatibility API

@iot_router.post("/s8/location")
async def s8_location_compatibility(data: dict) -> dict:
    """
    S8设备定位数据兼容性接口
    S8 device location data compatibility interface
    """
    try:
        # 推断设备ID / Infer device ID
        device_id = data.get("device_id") or data.get("imei") or "unknown_s8_device"
        
        # 使用IoT数据处理器处理数据 / Use IoT data processor to process data
        await data_processor.process_device_data(device_id, data)
        
        # 保持S8原有响应格式 / Maintain S8 original response format
        return {"flag": 1, "msg": "成功 / Success", "obj": {"test": 1}}
        
    except Exception as e:
        logger.exception("S8定位数据兼容性接口处理异常 / S8 location data compatibility interface processing error")
        return {"flag": 0, "msg": "失败 / Failed", "obj": {}}


@iot_router.post("/s8/health")
async def s8_health_compatibility(data: dict) -> dict:
    """
    S8设备健康数据兼容性接口
    S8 device health data compatibility interface
    """
    try:
        # 推断设备ID / Infer device ID
        device_id = data.get("device_id") or data.get("imei") or "unknown_s8_device"
        
        # 使用IoT数据处理器处理数据 / Use IoT data processor to process data
        await data_processor.process_device_data(device_id, data)
        
        # 保持S8原有响应格式 / Maintain S8 original response format
        return {"flag": 1, "msg": "成功 / Success", "obj": {"test": 1}}
        
    except Exception as e:
        logger.exception("S8健康数据兼容性接口处理异常 / S8 health data compatibility interface processing error")
        return {"flag": 0, "msg": "失败 / Failed", "obj": {}}